package com.zhm.demo;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Consumer;

public class Where<T> {

    public static class DefaultPropertyAccessorImpl<T> implements BiFunction<T, String, Object> {
        @Override
        public Object apply(T o, String property) {
            Field[] fields = o.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.getName().equals(property)) {
                    field.setAccessible(true);
                    try {
                        return field.get(o);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            return null;
        }
    }

    BiFunction<T, String, Object> propertyAccessor = new DefaultPropertyAccessorImpl<>();

    public void setPropertyAccessor(BiFunction<T, String, Object> propertyAccessor) {
        this.propertyAccessor = propertyAccessor;
    }

    Iterator<T> iterator;

    public Where(Iterator<T> iterator) {
        this.iterator = iterator;
    }

    // 修改filter方法签名，添加Consumer回调参数，返回类型改为void
    public void filter(String ruleJson, Consumer<T> resultCallback) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(ruleJson);
            JsonNode whereNode = rootNode.get("where");

            while (iterator.hasNext()) {
                T obj = iterator.next();
                if (evaluateCondition(whereNode, obj)) {
                    // 通过回调函数返回符合条件的对象，替代添加到列表
                    resultCallback.accept(obj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 递归评估条件
     */
    private boolean evaluateCondition(JsonNode conditionNode, T obj) {
        if (conditionNode == null || !conditionNode.isObject()) {
            return false;
        }

        // 处理OR逻辑
        if (conditionNode.has("OR")) {
            JsonNode orNode = conditionNode.get("OR");
            if (orNode.isArray()) {
                for (JsonNode node : orNode) {
                    if (evaluateCondition(node, obj)) {
                        return true;
                    }
                }
            }
            return false;
        }

        // 处理AND逻辑
        if (conditionNode.has("AND")) {
            JsonNode andNode = conditionNode.get("AND");
            if (andNode.isArray()) {
                for (JsonNode node : andNode) {
                    if (!evaluateCondition(node, obj)) {
                        return false;
                    }
                }
                return true;
            } else if (andNode.isObject()) {
                Iterator<Map.Entry<String, JsonNode>> fields = andNode.fields();
                while (fields.hasNext()) {
                    Map.Entry<String, JsonNode> field = fields.next();
                    JsonNode childNode = new ObjectMapper().createObjectNode().set(field.getKey(), field.getValue());
                    if (!evaluateCondition(childNode, obj)) {
                        return false;
                    }
                }
                return true;
            }
            return false;
        }

        // 处理比较条件
        Iterator<Map.Entry<String, JsonNode>> fields = conditionNode.fields();
        if (fields.hasNext()) {
            Map.Entry<String, JsonNode> field = fields.next();
            String property = field.getKey();
            JsonNode operatorNode = field.getValue();

            Iterator<Map.Entry<String, JsonNode>> operatorFields = operatorNode.fields();
            if (operatorFields.hasNext()) {
                Map.Entry<String, JsonNode> operatorField = operatorFields.next();
                String operatorName = operatorField.getKey();
                JsonNode valueNode = operatorField.getValue();

                Object propertyValue = propertyAccessor.apply(obj, property);
                return evaluateComparison(operatorName, propertyValue, valueNode);
            }
        }

        return false;
    }

    /**
     * 评估比较操作
     */
    private boolean evaluateComparison(String operatorName, Object propertyValue, JsonNode valueNode) {
        switch (operatorName) {
            case "startsWith":
                return propertyValue instanceof String && ((String) propertyValue).startsWith(valueNode.asText());
            case "gt":
                try {
                    Number numValue = (Number) propertyValue;
                    return numValue.doubleValue() > valueNode.asDouble();
                } catch (Exception e) {
                    return false;
                }
            case "equals":
                return Objects.equals(propertyValue, valueNode.asText());
            // 可以添加更多比较操作符的支持
            default:
                return false;
        }
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class User {
        private String name;
        private int profileViews;
        private String role;

        // 构造函数、getter和setter方法
    }

    public static void simpleTest() {
        List<User> userList = Lists.newArrayList();
        userList.add(new User("Eduardo", 100, "ADMIN"));
        userList.add(new User("Alena", 50, "USER"));
        userList.add(new User("Cduardo", 200, "USER"));
        userList.add(new User("Bduardo", 300, "ADMIN"));

        Iterator<User> userIterator = userList.iterator();


        // 定义属性访问器
        BiFunction<User, String, Object> propertyAccessor = (user, property) -> {
            switch (property) {
                case "name":
                    return user.getName();
                case "profileViews":
                    return user.getProfileViews();
                case "role":
                    return user.getRole();
                default:
                    return null;
            }
        };

        String ruleJson = """
                {
                    "where": {
                        "OR": [
                            {
                                "name": {
                                    "startsWith": "E"
                                }
                            },
                            {
                                "AND": [
                                    {
                                        "profileViews": {
                                            "gt": 0
                                        }
                                    },
                                    {
                                        "role": {
                                            "equals": "ADMIN"
                                        }
                                    }
                                ]
                            }
                        ]
                    }
                }
                """;

        ruleJson = """
                {
                    "where": {
                                "name": {
                                    "startsWith": "E"
                                }
                    }
                }
                """;

        Where<User> where = new Where<>(userIterator);
        where.filter(ruleJson, user -> {
            System.out.println("符合条件的用户: " + user);
            // 这里可以添加对单个符合条件对象的处理逻辑
        });
    }


    public static void main(String[] args) {

    }
}
